﻿using System;
using System.IO;
using System.Xml;

using Sunyi.Project.WebPoint.Common;

namespace Sunyi.Project.WebPoint.Configuration
{
    public static class SystemConfiguration
    {
        private const string ConnectionString = "ConnectionString";
        private const string SystemConfigurationFileName = "SystemConfiguration.xml";

        private static DateTime lastUpdateTime;
        private static readonly object SyncObject = new object();

        private static FileSystemWatcher systemConfigurationFileWatcher;

        public static string DBConnectionString
        {
            get
            {
                lock (SyncObject) return Database[ConnectionString];
            }
        }

        public static string CurrentVersion
        {
            get
            {
                lock (SyncObject)
                {
                    string version = PlatForm[WebPointGlobalConstant.Version];
                    if (string.IsNullOrEmpty(version)) version = AssemblyInformation.AssemblyVersion;

                    return version;
                }
            }
        }

        public static bool PersonnelServiceEnabled
        {
            get
            {
                lock (SyncObject)
                {
                    string authenticationMode = SystemConfiguration.Authentication[WebPointGlobalConstant.Mode];
                    return !string.IsNullOrEmpty(authenticationMode) && authenticationMode.Contains(WebPointGlobalConstant.Service);
                }
            }
        }

        public static string SystemName
        {
            get
            {
                lock (SyncObject)
                {
                    string systemName = SystemConfiguration.PlatForm[WebPointGlobalConstant.SystemName];
                    if (string.IsNullOrEmpty(systemName)) systemName = System.Environment.MachineName;

                    return systemName;
                }
            }
        }

        public static CommonConfiguration PlatForm
        {
            get;
            private set;
        }

        public static CommonConfiguration WebSite
        {
            get;
            private set;
        }

        public static CommonConfiguration Authentication
        {
            get;
            private set;
        }

        public static CommonConfiguration Database
        {
            get;
            private set;
        }

        public static CommonConfiguration AuditLog
        {
            get;
            private set;
        }

        static SystemConfiguration()
        {
            InitializeFileChangeWatcher();

            Initialize();
        }

        private static void InitializeFileChangeWatcher()
        {
            systemConfigurationFileWatcher = new FileSystemWatcher();
            systemConfigurationFileWatcher.BeginInit();
            systemConfigurationFileWatcher.IncludeSubdirectories = false;
            systemConfigurationFileWatcher.Path = EnvironmentSetting.ConfigurationFolderPath;
            systemConfigurationFileWatcher.Changed += new FileSystemEventHandler(SystemConfigurationFileWatcher_Changed);
            systemConfigurationFileWatcher.Filter = SystemConfigurationFileName;
            systemConfigurationFileWatcher.NotifyFilter = NotifyFilters.LastWrite;
            systemConfigurationFileWatcher.EnableRaisingEvents = true;
            systemConfigurationFileWatcher.EndInit();
        }

        private static void Initialize()
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(EnvironmentSetting.ConfigurationFolderPath + SystemConfigurationFileName);

            foreach (XmlNode node in xml.DocumentElement)
            {
                if (node.Name == WebPointGlobalConstant.PlatForm)
                {
                    PlatForm = new CommonConfiguration(node);
                }
                else if (node.Name == WebPointGlobalConstant.WebSite)
                {
                    WebSite = new CommonConfiguration(node);
                }
                else if (node.Name == WebPointGlobalConstant.Authentication)
                {
                    Authentication = new CommonConfiguration(node);
                }
                if (node.Name == WebPointGlobalConstant.Database)
                {
                    Database = new CommonConfiguration(node);
                }
                else if (node.Name == WebPointGlobalConstant.AuditLog)
                {
                    AuditLog = new CommonConfiguration(node);
                }
                else
                {
                    // Nothing to do.
                }
            }
        }

        private static void SystemConfigurationFileWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            string filePath = EnvironmentSetting.ConfigurationFolderPath + SystemConfigurationFileName;

            if (e.FullPath == filePath)
            {
                lock (SyncObject)
                {
                    try
                    {
                        FileInfo fileInfo = new FileInfo(filePath);
                        DateTime lastWriteTime = fileInfo.LastWriteTime;

                        if (lastWriteTime != lastUpdateTime)
                        {
                            Initialize();
                            lastUpdateTime = lastWriteTime;
                        }
                    }
                    catch
                    {
                        // TODO - Write log for the exception.
                        // Can't invoke Logger since Log System is not ready in this level.
                    }
                }
            }
        }
    }
}
